﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using MessageSystem.Managed;
using MessageSystem.Managed.Infrastructure;
using MessageSystem.Managed.Interface;

namespace MessageSystem.Managed.Rpc
{
    public class RpcSessionService
    {
        private object _implement;
        private RpcInvoker _invoker;
        private int _session;
        private Action _lost;
        private RpcDomain _domain;
        private Dictionary<Int32, object> _callbacks;
        private Int32 _nextOpCode;
        private RpcService _service;

        public RpcSessionService(RpcService svc,object impl, RpcInvoker invoker, int session, Action lost, RpcDomain domain)
        {
            _implement = impl;
            _invoker = invoker;
            _session = session;
            _lost = lost;
            _domain = domain;
            _callbacks = new Dictionary<int, object>(new Int32EqualityComparer());
            _nextOpCode = 0;
            _service = svc;
        }

        public void UnBind()
        {
            _service.UnBind(_session);
        }

        public void Invoke(UInt16 flags, Int16 methodid,Int32 OpCode,NetStream stream)
        {
            _invoker.Invoke(_implement, this, flags, methodid,OpCode,stream);
        }

        public void Return(UInt16 flags, Int16 methodid,Int32 OpCode,NetStream stream)
        {
            _invoker.Return(flags, methodid,OpCode,stream,this);
        }

        public Int32 PushCallback(object d)
        {
            _callbacks[_nextOpCode] = d;
            return _nextOpCode++;
        }

        public object PopCallback(Int32 nOpCode)
        {
            object result = null;
            if (_callbacks.TryGetValue(nOpCode, out result))
            {
                _callbacks.Remove(nOpCode);
            }

            return result;
        }

        public void FromServiceReturn(IMessage msg, bool encrypt,Int32 OpCode)
        {
            UInt16 flags = 0;
            if (encrypt)
                flags = RpcControl.SetEncrypt(flags);
            flags = RpcControl.SetReturn(flags);
            _domain.Invoke(msg, flags, _session, OpCode);
        }

        public void OnLost()
        {
            _lost();
        }
    }
}
